Polkadot技术篇 (3) 平行链: 攻克区块链不可能三角
区块链三角
阅读时间:20分钟 内含代码
核心问题:
区块链网络的功能一直有不可能三角之说。三角不可兼得:去中心化、可扩展性、安全性。
“区块链三角只能实现其中两个属性” – 以太坊创始人 Vitalik Buterin
图:Web3区块链网络分层架构 (目前已更新到Layer3, Layer4:可拓展合约层)
如何互补:
在Polkadot跨链网络通过分层模型实现多链异构结构实现三者兼备的功能。
Polkadot网络通过改造Layer1底层账本层:主要通过改善共识,增强安全性和去中心化程度;
Layer2的应用层和合约层实现多链并行的功能,在不同的属性上做加强和妥协,整个网络结构上实现三角的互补。
总体上是Polkadot是一个不是百分之百去中心化的多链异构的跨链网络,也在一定妥协的基础上实现安全性、互操作性和可拓展性。
图:举例 - 跨链网络协议layer1、layer2功能
互操作性:
Polkadot跨链网络技术在架构上能够克服克服区块链网络发展的瓶颈。
互操作能力(interoperability)是一个区块链网络满足去中心化、安全性、可扩展性三个属性兼具后可实现的功能。
Polkadot网络协议的核心实现互操作能力(interoperability)。当前不同链的信息和资产的转移只能通过中心化交易所,比如把一个币种换成另一个币种。
在波卡网络中,以中继链为核心互联的不同区块链能实现资产和信息的内部转账。在BTC、以太坊等网络通过桥接链接入后,
例如:把BTC跨以太坊或EOS的交易都可以在Polkadot的客户端钱包中实现转账。
可拓展性:
Polkadot网络的可拓展性体现在能够 横向拓展, 指的是不同链之间大量交易可以平行的进行处理。
Polkadot实现扩展性的关键在于:给平行链设置一个状态机 (state machine) 的网络机制,从而实现开发者能给不同平行链分配任务的功能,
这大大优化了数据的处理速度、每个节点的计算机在运行时所占内存也大大降低。
安全性:
Polkadot在Layer2 Off-Chain层实现了伞型安全架构,伞型体现在有多个校对人节点(collators)围绕一个平行链实行网络监管。少数验证人节点维护网络安全,依据验证人表现的好坏、是否作恶,验证人都会得到奖励和惩罚以此保证维护网络安全的验证人不会做恶。
Polkadot平行链技术实现
图:Polkadot网络角色, 平行链在Polkadot网络中的位置
平行链 (parachain) 是接入Polkadot网络协议的第三方的独立的区块链。
不同平行链连接到中继链实现数据传输和交换。平行链的搭建是Polkadot实现跨链、可扩展、互操作的关键之一。
我们会在下文刨析平行链的代码解释跨链功能的实现过程。
Parachain平行链架构,在真实状态下,并不是像上图那样生物学/工程电路图一般的架构。
开发架构上,平行链由三层语言层写出来的,分别是:
(1)逻辑层 src/lib.rs 用来表达平行链逻辑;
(2)编译层 wasm/lib.rs 当有必要用wrappers编译,例如将高级语言JavaScript中将JS类型转换成Rust,或在Rust中接收wasm类型并将其转为Rust类型;
(3)校对人(collator)层:主要由包括所有客户端上的校对人节点的main.rs文档或者自建模块比如Cargo,一个Rust语言默认的包管理工具、添加依赖项。
Parachain根目录也包含Cargo.toml文档作为编译平行链、运行校对人的依赖,包括运行校对人、标准Polkadot类型等的API:
[package]
name = "custom_parachain"
version = "0.1.0"
[dependencies]
polkadot-parachain = { path = "<path to polkadot/parachain>" }
polkadot-collator = { path = "<path to polkadot/collator>" }
polkadot-primitives = { path = "<path to polkadot/primitives>" }
... other libs
搭建Rust环境、Polkadot源码、Cargo.toml工具包如下:
curl https://sh.rustup.rs -sSf | sh
rustup update nightly
rustup default nightly
rustup target add wasm32-unknown-unknown --toolchain nightly # 安装rust环境并使其兼容wasm32工具
cargo install --git https://github.com/alexcrichton/wasm-gc
# 安装完支持Wasm的Rust环境后安装Wasm本体
git clone https://github.com/paritytech/polkadot.git # 输入源码
cd polkadot
./scripts/build.sh //构建Wasm二进制编译环境
cargo build # Builds all native code
cargo test –all //测试Wasm能不能跑出来
[package] //在每个文件夹和根目录都可以建立工具包文件
name = "custom_parachain"
version = "0.1.0"
[dependencies]
polkadot-parachain = { path = "<path to polkadot/parachain>" }
polkadot-collator = { path = "<path to polkadot/collator>" }
polkadot-primitives = { path = "<path to polkadot/primitives>" }
... other libs
逻辑层 src/lib.r
首先要创建的是src / lib.rs源。比如添加简单的逻辑以将一些新数据(例如从IoT设备收集的数据)引入链中。
第一行包括在源代码中指定的API,接口和数据类型,我们应该重复使用并实现它们以进行名称匹配:
//启动命令端
#![warn(missing_docs)] //忽略丢失文档
#[macro_use] //首先创建数据源例如从物联网设备中收集的收集导入到平行链中
extern crate parity_codec_derive;
extern crate parity_codec;
extern crate polkadot_parachain as parachain;
extern crate tiny_keccak;
use parity_codec::{Encode, Decode};
现在,我们将实现主要的平行链数据类型 data type。另外,从某些标准Polkadot数据类型的继承,这里暂时就用预置后的哈希和编码属性。
//Rust语言使用cargo创建工程相对别的语言明显好找启动点,库是lib.rs标记,主程序main.rs标记,波卡链的主程序在polkadot/polkadot/src/main.rs中。
//执行主要的平行链数据类型,使用从标准polkadot数据类型中继承的数据用来hashing和encoding,标准模板如下:
#[derive(Default, Clone, Hash, Eq, PartialEq, Encode, Decode)]
pub struct HeadData {
pub block_number: u64,
pub parent_hash: [u8; 32],
pub state_hash: [u8; 32],
}
#[derive(Default, Clone, Encode, Decode)]
pub struct BlockData {
pub data_hash: [u8; 32],
pub some_data: IotData,
}
//以下是自定义的数据类型,这里把数据上链
#[derive(Default, Clone, Encode, Decode)]
pub struct IotData {
pub iotId: u64,
pub parameter: [char; 20],
pub value: u64,
}
现在,我们继续runtime。这里要实现任何链上逻辑和公共API,能从平行链节点或dApp能访问并遵从该runtime。在本例中,我们将创建一个用于执行自定义逻辑的函数,以及一个用于验证区块和生产新的区块头的函数:
//平行链的运作逻辑构造如下,用来执行所有的链上运作逻辑、和所有能被平行节点和dApps所访问的公开API,构造如下:
pub fn produce_valid_header(
parent_hash: [u8; 32],
parent_head: HeadData,
block_data: &BlockData,
) - Result<HeadData, Debug> {
//所有检测放在如下框中
debug_assert_eq!(parent_hash, parent_head.hash());
let calculated_hash = ::tiny_keccak::keccak256( block_data.some_data[..] )
if calculated_hash != block_data.data_hash {
return Err(Debug);
}
let new_state_hash = ::tiny_keccak::keccak256( block_data.encode().as_slice() );
Ok(HeadData {
block_number: parent_head.block_number + 1,
parent_hash,
state_hash: new_state_hash,
})
}
pub fn execute(
parent_hash: [u8; 32],
parent_head: HeadData,
some_data: &SomeData,
) -> Result<HeadData, Debug> {
let block_data: BlockData;
//Custom operations: 将数据整理至区块
match produce_valid_header( parent_hash, parent_head, &block_data ) {
Ok(new_head) => new_head,
Err(_) => Err(Debug),
}
接下来我们要码一个接口,用于验证平行链生成的区块 (interface for validating parachain blocks),内含validate函数以及自定义的bug处理模组(a custom error handling function)
首先,我们从平行链runtime中导入必要的模块和数据类型。custom_parachain是我们在上一步中实现的自定义的逻辑函数:
接下来我们执行这个函数 (Polkadot提供了链上数据交互的一些模版)
pub extern fn validate(offset: usize, len: usize) -> usize {
//该层主要功能是添加验证平行链区块功能,功能角色被命名为验证人validator。
let params = unsafe { ::parachain::wasm_api::load_params(offset, len) };
let parent_head = HeadData::decode(&mut ¶ms.parent_head[..])
.expect("invalid parent head format.");
let block_data = BlockData::decode(&mut ¶ms.block_data[..])
.expect("invalid block data format.");
let parent_hash = ::tiny_keccak::keccak256( ¶ms.parent_head[..]);
match ::custom_parachain::produce_valid_header( parent_hash, parent_head, &block_data) {
Ok(new_head) => parachain::wasm_api::write_result(
ValidationResult { head_data: new_head.encode() }
),
Err(_) => panic!("validation failure"),
}
}
//可以自行添加一些自己喜欢的bug处理模组
Collator校对人层
这里会码 所有校对人节点的逻辑,从平行链调用逻辑
//从平行链逻辑中调用函数用来打包交易、因为校对人架构也要有时成为验证人在管理网络
use custom_parachain::{HeadData as CustomHead, BlockData as CustomBody, IotData};
use primitives::parachain::{HeadData, BlockData, Id as ParaId, Message, Extrinsic};
use collator::{InvalidHead, ParachainContext, VersionInfo};
创世区块的架构也需要放入校对人节点:
//创世区块架构
const GENESIS: CustomHead = CustomHead {
block_number: 0,
parent_hash: [0; 32],
state_hash: [some_value],///calculated initial hash value
};
const GENESIS_BODY: CustomBody = CustomBody {
data_hash: [some_value],
some_data: IotData {
iotId: 0,
parameter: ['n', 'o', 'n', 'e'],
value: 0,
}
};
平行链虽然和一般区块链有点不一样,但也能从一般的区块链数据库、常见的逻辑派生出来。有些有Polkadot模板,同时加入强制性的produce_candidate函数,因为校对人的功能如此。
#[derive(Clone)]
struct CustomContext {
db: Arc<Mutex<HashMap<CustomHead, CustomBody>>>,
}
impl ParachainContext for CustomContext {
fn produce_candidate<I: IntoIterator<Item=(ParaId, Message)>>(
//输入备选节点函数produce_candidate
& self,
last_head: HeadData,
ingress: I,
) -> Result<(BlockData, HeadData, Extrinsic), InvalidHead>
{
//从上一个区块头得到母区块
//从创世区块主体的数据库中得到前一个区块数据
...
//在此处可以输入自设的区块产生逻辑
...
let next_head = ::custom_paracain::execute( parent_head.hash(), parent_head, &next_body );
let encoded_head = HeadData(next_head.encode());
let encoded_body = BlockData(next_body.encode());
//命令符:将区块存储至数据库
db.insert(next_head.clone(), next_body);
Ok((encoded_body, encoded_head, Extrinsic { outgoing_messages: Vec::new() }))
}
}
创世区块所包含的数据值,然后需要建立与校对人的“联系”使得校对人能够挑选最适合网络的区块,将区块推荐给验证人进行验证,进入数据传输的下一步。
fn main() {
let id: ParaId = 100.into();
...
let encoded = GENESIS.encode();
let context = CustomContext {
db: Arc::new(Mutex::new(HashMap::new())),
};
....
let res = ::collator::run_collator(
context,
id,
exit_function,
key_function,
::std::env::args(),
VersionInfo {
......
}
);
...
}
至此,所设置框架的平行链就可以进行编译和部署了。部署及查看平行链可以参考Polkadot wiki,目前大约需要5DOTS可参与测试网,部署后的平行链可以再在Polkascan区块链浏览器中查看。
小结:平行链的了解必读
本文从平行链入手,讲解Polkadot的互操作性、安全性、可扩展化是如何搭建的。
本篇是Polkadot「技术篇」的第三篇了,继上两篇「加强安全保护和拦截网络攻击」和「无需抵押领取免费KSM」后的第三篇代码解读。
未来将继续更新「了解必读」篇,按照上一篇「思维导图」的脉络细讲Polkadot网络架构如何实现网络功能。
编译 / ShawnRingLin
原文:Horbonos, P. (2019). How to Build a Parachain on Polkadot. Apriorit.
活动介绍
今天的开发者们越来越多地接触到开源自由的精神,首先是代码、软件和硬件的开源,进一步,是应用和数据之间跨链的安全开放,甚至再到新一代的由用户自己掌握的互联网。最近快速发展的几个概念,Rust语言、跨链技术到Web3.0分布式互联网,就是在这一条开源世界的技术道路中不断探索。
PolkaBase技术驱动Meetup第二期,我们连同Grin、SoLid和Rust CC开发社区的创始人们,在3个小时的时间里,带大家从开发者的角度学习这些开源世界的重要技术——它们的原理是什么、如何实现、又会带来怎样的火花。
时间地点
时间:2019.12.4
地点:浙江省萧山区市心北路2000号ITC归谷国际中心办公楼5楼
分享流程
18:30-19:00 签到、交流
19:00-19:20 Grin社区Xiaojay:Rust实现的mimblewimble协议与Grin
19:20-19:40 Rust CC社区Sun:跨链之路的演进
20:00-20:20 SoLiD中文社区谢扬:万维网之父的数据主权革命
20:20-20:40 PolkaBase技术社区Charlie:当开源技术走进Web3区块链时代
20:40-21:00 Panel: Rust、跨链到Web3.0的开源世界
21:00-21:30 问答、自由交流
嘉宾主题
Grin社区:Xiaojay独立开发者。Grin钱包Niffler开发者、Grinpay创始人、Grin中国社区成员。
主题:Rust实现的mimblewimble协议与Grin
简要介绍mimblewimble协议技术原理(Rust实现),以及Grin开源项目运作模式。
Rust CC社区:Sun
CypherLink联合创始人&TDN作者
A crytographer,programmer,idealist。一位喜欢开源文化和社区的程序员,目前付诸精力于密码学和区块链的研究和应用落地。2019年联合成立了CypherLink(cypherlink.io)组织,探索解决数据安全和隐私保护问题。
主题:跨链之路的演进:1. 什么是跨链技术;2. 早期的跨链思想;3. 目前的跨链方案;4. TDN的跨链理念和实现
SoLiD中文社区:谢扬
蒸汽记忆创始人,SoLiD中文社区发起人。曾任好东西传送门CTO,负责知识推荐和舆情监测系统研发、服务数十万用户;曾任字节跳动Hacker,负责公司每日过亿请求Serverless平台研发。
主题:万维网之父的数据主权革命
SoLiD是万维网之父发起的重塑互联网项目,其带来了全新的Web应用开发范式,目的是将数据归还于用户所有和控制,并由用户授权哪些人和哪些应用能够读写自己的数据。此次分享涵盖Web的起源,SoLiD的入门介绍和SoLiD的开发体验,以及对未来Web的预测。
PolkaBase技术社区:Charlie
PolkaBase波卡生态社区主要推动者之一,翻译数十篇Polkadot专业文章,多次协助Polkadot中国活动现场同声传译。达沃斯全球杰出青年社区北京Hub成员,全奖荷兰奈耶诺德商业大学金融管理硕士,曾任ThingsCon物联网社区中国负责人,曾为多个区块链项目做战略顾问。
主题:当开源技术走进Web3区块链时代
结合目前最新的Web3生态发展动态,分享目前开源技术和区块链技术的结合,包括未来技术社区生态可以进一步提高和发展的思考。
主办方
关于PolkaBase
PolkaBase是以波卡技术为基础的区块链3.0生态,致力于打造一个能推动区块链技术与应用落地、产生优质内容和产品价值、并吸引区块链行业外部资源与团队的新一代社区;在技术普及、生态孵化、高校与产业联合、价值用户和国际化五大方面,弥补现有社群的不足,推动生态的深化与发展。